<?php
namespace Framework;

use Carbon\Carbon;
use Illuminate\Support\Facades\Facade;
use InfluxDB\Database;
use InfluxDB\Point;

/**
 * Class InfluxDB
 * @package Framework
 * @mixin Database
 */
class InfluxDB extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return Database::class;
    }

    public static function select(string $query, array $params = []): array
    {
        $res = static::query($query, $params);
        return $res->getPoints();
    }

    public static function getBuilder()
    {
        return static::getQueryBuilder();
    }

    public static function insert(string $table,
                                  array $tags = [],
                                  array $fields = [],
                                  $value = null,
                                  $timestamp = null)
    {
        $point = new Point($table, $value, $tags, $fields, $timestamp);
        dispatch(function () use ($point) {
            InfluxDB::writePayload((string)$point);
        });
    }

    public static function getPoints(string $table, array $where = [], string $order = 'time desc', int $limit = 20): array
    {
        $query_where = [];
        foreach ($where as $field => $item) {
            if (is_numeric($field)) {
                if (is_string($item) || is_numeric($item)) {
                    $query_where[] = $item;
                } else if (is_array($item)) {
                    if (count($item) === 2) {
                        $query_where[] = "{$item[0]} = '{$item[1]}'";
                    } else if (count($item) === 3) {
                        $query_where[] = "{$item[0]} {$item[1]} '{$item[2]}'";
                    } else {
                        throw new \InvalidArgumentException('where');
                    }
                } else {
                    throw new \InvalidArgumentException('where');
                }
            } else if (is_string($field)) {
                $str_where = "$field";
                if (is_string($item) || is_numeric($item)) {
                    $str_where .= " = '$item'";
                } else if (is_array($item) && count($item) === 2) {
                    $str_where .= " {$item[0]} '{$item[1]}'";
                } else {
                    throw new \InvalidArgumentException('where');
                }
                $query_where[] = $str_where;
            } else {
                throw new \InvalidArgumentException('where');
            }
        }

        $res = InfluxDB::getBuilder()->from($table)
            ->where($query_where)
            ->orderBy($order, '')
            ->limit($limit)
            ->getResultSet()
            ->getPoints();

        return $res;
    }

    public static function getData(string $table_name, array $where = []): array
    {
        $ret = [];

        $list = InfluxDB::getPoints($table_name, $where);
        if ($list) {

            $ret[] = collect($list)->map(function ($item) {
                $time = $item['time'];
                $time = explode('.', $time)[0] . '+00:00';
                $item['time'] = Carbon::parse($time)
                    ->setTimezone(config('app.timezone'))
                    ->format('Y-m-d H:i:s');
                return $item;
            })->toArray();

            $ret[] = [
                'last_time' => $list[count($list) - 1]['time']
            ];
        } else {
            $ret = [[], []];
        }

        return $ret;
    }
}
